using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
using Sirenix.OdinInspector;
using UnityEngine.InputSystem;
using UnityEngine.Animations.Rigging;
/// <summary>
/// 作为处理核心， 兼具了流式输入+Trigger输入的功能
/// 只处理, 不管理, 管理需要 Input层和Skill层协商
/// </summary>
[ExecuteAlways]
[RequireComponent(typeof(VActState_Loader), typeof(VActSkill_Loader), typeof(VActInput))]

public class VActProcessor : MonoBehaviour
{
    #region 
    //这里是加载设置, 应该由外部类加载, 先放到最基层
    private bool settingLoaded = false;
    public void LoadSetting(VActStateBase stateBase = null, VActSkillBase skillBase = null)
    {
        if (settingLoaded) return;
        if (SFrameworkGate.InEditor && !SFrameworkGate.IsPlaying) return;
        var input = gameObject.UniqueComponent<VActInput>();
        gameObject.UniqueComponent<VActState_Loader>().Init(this, input, stateBase);
        gameObject.UniqueComponent<VActSkill_Loader>().Init(this, input, skillBase);
        input.Init(this);

        data = gameObject.UniqueComponent<VActProcessorData>();
        settingLoaded = true;
    }
    #endregion
    public VActBehaviour behaviour => GetComponent<VActBehaviour>();
    [HideInInspector] public VActProcessorData data;
    public VActMotionVectorMechine mechine;
    [HorizontalGroup("Idle")] public AnimationClip idleClip;
    public VS_MulitPassAnimationGraph VS_MulitPassAnimationGraph;
    public VS_AnimationGraph VS_AnimationGraph;
    public VS_EntityGraph VS_EntityGraph;
    public VS_VacancyGraph VS_VacancyGraph;
    public VS_InteractGraph VS_InteractGraph;
    public VS_ControlGraph VS_ControlGraph;
    public VS_AudioGraph VS_AudioGraph;

    [LabelText("启用遮罩动画图")] public bool avatarGraphEnable = false; //先看宝效果
    private void Start()
    {
        Init();
        LoadSetting();
        OnInit?.Invoke();
    }
    public Action OnInit;
    public void Init()
    {
        if (avatarGraphEnable) VS_MulitPassAnimationGraph = new VS_MulitPassAnimationGraph(gameObject);
        else VS_AnimationGraph = new VS_AnimationGraph(gameObject);
        VS_EntityGraph = new VS_EntityGraph(gameObject);
        VS_VacancyGraph = new VS_VacancyGraph(gameObject);
        VS_InteractGraph = new VS_InteractGraph(gameObject);
        VS_ControlGraph = new VS_ControlGraph(gameObject);
        VS_AudioGraph = new VS_AudioGraph(gameObject);
        gloablTable = new List<TimelineClip>();
        mechine = new VActMotionVectorMechine(this, transform);
        processorEnable = true;
        if (avatarGraphEnable) VS_MulitPassAnimationGraph.SetDefaultAnimation(idleClip);
        else
            this.SetIdle(idleClip);
    }
    private void OnDisable()
    {
        if (!processorEnable) return;
        processorEnable = false;
        VS_AnimationGraph?.Destroy();
        VS_MulitPassAnimationGraph?.Destroy();
        VS_EntityGraph?.Destroy();
        VS_VacancyGraph?.Destroy();
        VS_InteractGraph?.Destroy();
        VS_ControlGraph?.Destroy();
        VS_AudioGraph?.Destroy();
    }
    [LabelText("核心状态")]
    public bool processorEnable = false;
    public float graphTime;

    private List<TimelineClip> gloablTable;
    private void FixedUpdate()
    {

    }
    [HorizontalGroup("Idle"), Button]
    private void FixPose()
    {
        VS_AnimationGraph.ForceInitGraph();
        0.1f.Delay(VS_AnimationGraph.baseGraph.Stop);
    }
    //这个地方是根据clip类型支持动画的
    public VSkillStateGraphBase GetGraph(VSClipType clipType) => clipType switch
    {
        VSClipType.Animation => VS_AnimationGraph,
        VSClipType.Vacancy => VS_VacancyGraph,
        VSClipType.Entity => VS_EntityGraph,
        VSClipType.Interact => VS_InteractGraph,
        VSClipType.Control => VS_ControlGraph,
        VSClipType.Audio => VS_AudioGraph,
        _ => throw new Exception("no Match Graph")
    };
    #region  Extension _ Rig
    [LabelText("启用Rig")][OnValueChanged("OdinCall_SwitchExtension_Rig")] public bool rigEnable;
    [HideInInspector] public VRig rig;
    public void OdinCall_SwitchExtension_Rig()
    {
        if (rigEnable)
        {
            rig = gameObject.UniqueComponent<VRig>();
            rig.Init();
        }
        else
        {
            rig?.OnUnLoad();
            gameObject.RemoveComponent<VRig>();
            rig = null;
        }
    }
    #endregion
    public Dictionary<int, Delegate> onGraphActions = new();
    private void UniqueAddAction<T>(ref T d1, T d2) where T : Delegate
    {
        if (d2 == null)
        {
            d1 = null;
            return;
        }
        var actHash = d2.GetHashCode();
        if (!onGraphActions.ContainsKey(actHash))
        {
            onGraphActions.Add(actHash, d2);
            d1 = (T)Delegate.Combine(d1, d2);
        }
        else
        {
            print("发生重复订阅,已排除");
        }
    }
    /// <summary>
    /// 当AnimationGraph完全回退到idle状态时调用
    /// </summary>
    public Action onTransDefault
    {
        get => VS_AnimationGraph?.onTransDefault;
        set => UniqueAddAction(ref VS_AnimationGraph.onTransDefault, value);
    }
    //或者说这个空置域其实只接受某些动作 
    public Action<AnimationClip> onExitAnimation
    {
        get => VS_AnimationGraph.onExitAnimation;
        set => UniqueAddAction(ref VS_AnimationGraph.onExitAnimation, value);
    }
    //多一层enableInput总归是丰富的和好的, 而且顺理成章
    public Action<List<VVacancyActMapper>> onEnterVacancyStringArgs; //就是说整个还得加一层过滤器

    public Action<string, string> onWriteParam
    {
        get => data.onWriteParam;
        set => UniqueAddAction(ref data.onWriteParam, value);
    }

    public Func<bool> onInteract
    {
        get => VS_InteractGraph.onInteract;
        set => UniqueAddAction(ref VS_InteractGraph.onInteract, value);
    }
    public Action<VAct> onEnterNewAct;
    public Action<string> onAskEnterAct;
    public VAct GetCurAct => GetComponent<VActInput>().curDoingAct;//不知道这块层级怎么处理先这么写

    public static Dictionary<Type, Action<VActProcessor, object>> processActions;




    private VAnimation processingVAnimation;

    public void ContinueAnim(VAnimation vAnimation = null)
    {
        // continue的屏蔽应该是交给processor做的, 对graph的调用机制尽量简单
        //明天过来先把状态转移图写了
        if (vAnimation == null)
        {

        }
        else
        {
            if(vAnimation.hasPre){
                //一个阻塞等待播完vanimaiton.pre然后持续播runtime
            }
        }
    }
}

public static class VActProcessorExtension
{
    //这里根据State中会用到的资源丰富变体行为

    /// <summary>
    /// 手动管理状态
    /// </summary>
    /// <param name="processor"></param>
    /// <param name="animationClip"></param>
    public static void ContinueState(this VActProcessor processor, AnimationClip animationClip = null)
    {
        if (animationClip == null)
        {
            processor.VS_AnimationGraph.TransDefault();
        }
        else
        {
            processor.VS_AnimationGraph.ContinueAnimationClip(animationClip);
        }
    }



    //图的支持还得更加完善一些, 人物可以丝滑过渡,但是像这种带了眼睛帧动画的就得直接转 
    public static void TriggerState(this VActProcessor processor, AnimationClip animationClip = null)
    {
        if (animationClip == null) processor.VS_AnimationGraph.SetDefault();
        else processor.VS_AnimationGraph.TriggerAnimationClip(animationClip);
    }

    public static void DirectorSetClip(this VActProcessor processor, AnimationClip animationClip = null)
    {
        if (animationClip == null)
        {
            processor.VS_AnimationGraph.SetClip(null, 1);
            // processor.DoState();
            // 那么问题就是这里的硬变化怎么做软, 怎么用上过渡
        }
        else
            processor.VS_AnimationGraph.SetClip(animationClip, 1);
    }


    public static void SetIdle(this VActProcessor processor, AnimationClip animationClip = null)
    {
        var Director = processor.GetComponent<PlayableDirector>();
        if (Director != null && Director.enabled) return;
        processor.VS_AnimationGraph.SetDefaultAnimation(animationClip);
        processor.onTransDefault?.Invoke();
    }

    public static void WriteSkillParam(this VActProcessor processor, string key, string value)
    {
        var data = processor.GetComponent<VActProcessorData>();
        data.Write(key, value);
    }

    public static void Continue(this VActProcessor processor, VAsset asset)
    {
        switch (asset.assetType)
        {
            case (int)VAssetType.AnimationClip:
                var animation = asset as VAnimation;
                processor.ContinueState(animation.runtimeClip);
                break;
            case (int)VAssetType.AudioClip:
                break;
            default:
                return;
        }
    }
    public static void Trigger(this VActProcessor processor, VAsset asset)
    {
        switch (asset.assetType)
        {
            case (int)VAssetType.AnimationClip:
                var animation = asset as VAnimation;
                processor.TriggerState(animation.runtimeClip);
                break;
            case (int)VAssetType.AudioClip:
                break;
            default:
                return;
        }
    }
    public static void Continue(this VActProcessor processor, string assetName) //这里要求一个name索引的全局资源 管理器
    {
        processor.Continue(assetName.ToAsset());

    }
    public static void Trigger(this VActProcessor processor, string assetName) //这里要求一个name索引的全局资源 管理器
    {
        processor.Trigger(assetName.ToAsset());
    }


    public static void Trigger(this VActProcessor processor)
    {

    }

    public static void WalkTo(this VActProcessor processor, Vector3 position)
    {

    }

    public static void Speak(this VActProcessor processor, string text, float delay = 0)
    {
        var TTS = processor.GetComponent<VTTS>();
        var source = processor.GetComponent<AudioSource>();
        if (TTS == null) return;
        TTS.Speak(text, (wav, speech) =>
        {
            source.clip = wav;
            //source.Play();
            if (delay == 0) source.Play();
        });

        if (delay != 0) delay.Delay(source.Play);
    }
}